package org.lsp.io.logger;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;

import org.lsp.io.files.FileLocker;

public abstract class SysLogger {
	public enum Level {
		WARN, ERROR, CRASH
		/*
		 * "WARN" level is intended for minor issues. "ERROR" level is intended
		 * for troublesome conflicts. "CRASH" level is intended for irreversible
		 * errors which cause the application to crash.
		 */
	};

	public static final void log(final Exception e, final String errCode,
			final Level severityLevel) {
		String s = "";
		Boolean firstFlag = Boolean.TRUE;
		final StackTraceElement[] st = e.getStackTrace();
		s += "Level " + severityLevel + "\n";
		for (final StackTraceElement element : st) {
			final int l = element.getLineNumber();
			if (l > 0) {
				if (firstFlag) {
					s += "\t\t" + errCode + " - " + e.getClass().getName()
							+ " raised in line " + l + " of "
							+ element.getClassName() + ": " + element + "\n";
					firstFlag = Boolean.FALSE;
				} else {
					s += "\t\t\t" + e.getClass().getName() + " from line " + l
							+ " of " + element.getClassName() + ": " + element
							+ "\n";
				}
			}
		}
		SysLogger.log(s);

		if (severityLevel == Level.CRASH) {
			System.exit(-1);
		}
	}

	private static final void log(final String text) {
		SysLogger.writeToFile(new SimpleDateFormat("HH:mm:ss").format(Calendar
				.getInstance().getTime()) + " - " + text);
	}

	private static final void writeToFile(final String text) {
		FileLocker.getLock(Paths.get("logs").toFile());
		if (!Files.exists(Paths.get("logs"))
				|| (Files.exists(Paths.get("logs")) && !Paths.get("logs")
						.toFile().isDirectory())) {
			try {
				Files.deleteIfExists(Paths.get("logs"));
				Files.createDirectory(Paths.get("logs"));
			} catch (final IOException e) {
				// Don't call the log again because it'll be a recursive
				// disaster
			}
		}
		FileLocker.releaseLock(Paths.get("logs").toFile());

		final DateFormat dateFormat = new SimpleDateFormat("yyyy MM dd");

		final String today = dateFormat
				.format(Calendar.getInstance().getTime());

		FileLocker.getLock(Paths.get("logs", today + ".log").toFile());
		if (!Files.exists(Paths.get("logs", today + ".log"))) {
			try {
				Files.createFile(Paths.get("logs", today + ".log"));
			} catch (final IOException e) {
				// Don't call the log again because it'll be a disaster
			}
		}
		try {
			Files.write(Paths.get("logs", today + ".log"),
					text.getBytes("ISO-8859-1"), StandardOpenOption.APPEND);
		} catch (final IOException e) {
			// Don't call the log again because it'll be a disaster
		}
		FileLocker.releaseLock(Paths.get("logs", today + ".log").toFile());
	}
}
